home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Science⁄Math
/
VideoToolbox
/
VideoToolboxSources
/
TranslateLinefeeds.c
< prev
next >
Wrap
Text File
|
1993-12-15
|
7KB
|
193 lines
/*
TranslateLinefeeds.c helps to resolve an incompatibility between code resources
generated by the THINK C compiler that are linked with the MPW stdio library.
The problem is that MPW and THINK C have adopted different solutions to the
problem that Standard C specifies that linefeeds should be represented as '\n'
(normally 10) inside programs, yet Apple, in their wisdom, decided that
linefeeds should be represented by 13 (normally '\r') in Macintosh ASCII text
files. The problem is handled invisibly by both compilers. MPW redefines '\n' to
mean 13. THINK C translates 13 to 10 (and vice versa) when writing and reading
text streams. Unfortunately, when you compile THINK C code resources that call
the MPW stdio library both solutions are eliminated and the old problem raises
its ugly head.
TranslateLinefeeds.c intercepts the calls to the (MPW) stdio library and partially
implements the THINK C stdio library convention of translating \n to \r and vice
versa on input and output to text files. Let's call this "linefeed translation".
(As in the THINK C stdio library, no translation is performed for binary files.)
These routines should only be used by THINK C code resources that must use the
MPW stdio library (because the MPW C stdio library doesn't do linefeed
translation). Don't change your C programs; use the standard names for the stdio
library routines and just #include the TranslateLinefeeds.h header (after stdio.h).
The TranslateLinefeeds.h header uses preprocessor macros to redirect nearly all the
stdio calls to this file, which interposes linefeed translation and calls the
(MPW) stdio library.
I've implemented all the i/o routines in stdio.h except fscanf and scanf.
They're difficult to handle, and I suspect that most uses of those routines
wouldn't distinguish /n from /r anyway.
All the printf-related routines are funneled through vfprintfTL. The actual
i/o is done by vfprintf(). If it's a "text" stream (as opposed to a "binary"
stream), then we translate the format string before calling vfprintf(), and
translate again afterwards, restoring the original string. This is a pretty good
solution, translating most of the linefeeds, but it fails to translate linefeeds
that appear in string and char arguments.
Our implementation of translation is incomplete for printf et al., and
nonexistent for scanf and fscanf because scanning the variable argument list
would require too much effort, requiring us to implement a large fraction of the
printf/scanf code: parsing the format string into tokens, retrieving each
argument, and passing them one at a time to fprintf/scanf.
The time overhead of these routines is negligible. All stdio functions that may
be implemented as inline macros are redefined by TranslateLinefeeds.h as new inline
macros that call the original routines.
Note that the getchar and putchar macros in TranslateLinefeeds.h assume that stdin
and stdout are "text" streams, though I haven't checked whether this is
guaranteed by Standard C.
For debugging, disabling the TRANSLATE flag results in the identity translation,
making all the code innocuous.
HISTORY:
7/31/93 dgp wrote it.
7/31/93 dgp Added support for MPW stdio library.
9/20/93 dgp Rewrote vfprintfTL to work with text strings of unlimited length.
Documented limitation of the new vfprintfTL. Implemented
getc, putc, getchar, and putchar as inline macros, in TranslateLinefeeds.h.
*/
#include <TranslateLinefeeds.h>
#include <string.h>
#undef fread
#undef fwrite
#undef fgetc
#undef ungetc
#undef fputc
#undef gets
#undef fgets
#undef fputs
#undef vfprintf
#define TRANSLATE 1 /* set this to zero for identity translation, for debugging */
unsigned char translateLinefeed[256]={
#if TRANSLATE
0,1,2,3,4,5,6,7,8,9,13,11,12,10,14,15,16,17,18,19
#else
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
#endif
,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39
,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59
,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79
,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99
,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119
,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139
,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179
,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199
,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219
,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
};
void TranslateLinefeeds(register char *s,register size_t n)
{
if(s!=NULL)for(;n>0;n--)*s++=translateLinefeed[(unsigned char)*s];
}
size_t freadTL(void *s,size_t size,size_t numitems,FILE *stream)
{
numitems=fread(s,size,numitems,stream);
if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
return numitems;
}
size_t fwriteTL(void *s,size_t size,size_t numitems,FILE *stream)
{
size_t n;
if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
n=fwrite(s,size,numitems,stream);
if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
return n;
}
int fgetcTL(FILE *stream)
{
char c;
c=fgetc(stream);
if(IS_TEXT(stream))return translateLinefeed[(unsigned char)c];
else return c;
}
char *fgetsTL(char *string,int n,FILE *stream)
{
char *s;
s=fgets(string,n,stream);
if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
return s;
}
int fputcTL(int c,FILE *stream)
{
int i;
if(IS_TEXT(stream))c=translateLinefeed[(unsigned char)c];
return fputc(c,stream);
}
int fputsTL(char *s,FILE *stream)
{
int error;
if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
error=fputs(s,stream);
if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
return error;
}
int fprintfTL(FILE *stream,const char *format,...)
{
va_list args;
int n;
va_start(args,format);
n=vfprintfTL(stream,format,args);
va_end(args);
return n;
}
char *getsTL(char *string)
{
char *s;
s=gets(string);
if(IS_TEXT(stdin))TranslateLinefeeds(s,strlen(s));
return s;
}
int printfTL(char *format,...)
{
va_list args;
int n;
va_start(args,format);
n=vfprintfTL(stdout,format,args);
va_end(args);
return n;
}
/*
In vfprintfTL we only translate the format string. We'll miss linefeeds that
are hiding in char and string arguments in the variable argument list. Finding
those would require a much more elaborate program, which would parse the format
string.
*/
int vfprintfTL(FILE *stream,const char *format,va_list args)
{
int n;
if(IS_TEXT(stream))TranslateLinefeeds((char *)format,strlen((char *)format));
n=vfprintf(stream,format,args);
if(IS_TEXT(stream))TranslateLinefeeds((char *)format,strlen((char *)format));
return n;
}
int vprintfTL(char *format,va_list args)
{
return vfprintfTL(stdout,format,args);
}